# -*- coding: utf-8 -*-
import sock
import time
from datetime import datetime, timedelta

import select

# CRC-16-CCITT查找表
auchCRCHi = [
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
    0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
    0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
    0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
    0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
    0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
    0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
    0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
    0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40]

auchCRCLo = [
    0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
    0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
    0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
    0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
    0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
    0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
    0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
    0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
    0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
    0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
    0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
    0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
    0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
    0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
    0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
    0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
    0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
    0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
    0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
    0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
    0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
    0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
    0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
    0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
    0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
    0x43, 0x83, 0x41, 0x81, 0x80, 0x40
]


def hex_to_bytes(hex_str):
    return bytes.fromhex(hex_str)


def decimal_to_hex(numbers):
    return ''.join(format(num, '02X') for num in numbers)


def bytes_to_hex(byte_array):
    return ''.join(format(byte, '02x') for byte in byte_array)


# CRC-16的计算函数
def crc16(puchMsg: bytes) -> str:
    """计算CRC-16校验和"""
    uchCRCHi = 0xFF
    uchCRCLo = 0xFF

    for byte in puchMsg:
        uIndex = uchCRCLo ^ byte
        uchCRCLo = uchCRCHi ^ auchCRCHi[uIndex]
        uchCRCHi = auchCRCLo[uIndex]

    crc = (uchCRCHi << 8) | uchCRCLo
    return f"{crc:04X}"


def create_tcp_connection(server_ip, server_port):
    sock = sock.socket(sock.AF_INET, sock.SOCK_STREAM)
    sock.connect((server_ip, server_port))
    print(f"已连接到服务器 {server_ip}:{server_port}")
    return sock


def close_tcp_connection(sock):
    print("关闭连接")
    sock.close()


def send_messages(sock, hex_messages):
    for hex_msg in hex_messages:
        message = hex_to_bytes(hex_msg)
        time.sleep(1)
        print(f"发送: {hex_msg}")
        sock.sendall(message)
        if select.select([sock], [], [], 1)[0]:
            data = sock.recv(1024)
            print(f"接收: {bytes_to_hex(data)}")


# 转化为16进制字符串
def formatx(number):
    if number >= 0:
        return format(number, '02X')
    else:
        # 处理负数，使用与你提供的相同的逻辑
        return format((number + (1 << 8)) & ((1 << 8) - 1), '02X')

def format6(number):
    if number >= 0:
        return format(number, '06X')
    else:
        # 处理负数，使用与你提供的相同的逻辑
        return format((number + (1 << 8)) & ((1 << 8) - 1), '06X')

# 登录数据
TBOXCode = format(40041110, '08X').upper()  # 40041110
# hardversion = "0300"  softversion = "0101B4" SIM= "89860624700093459875"

vin = "YH974329483295032".encode('ASCII').hex().upper()  # 17位VIN号车架号  LZ5RB7D3XLB002010
# vin="FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
data0 = "5CADF34E"  # 固定数据
data = f"D2CF003704{TBOXCode}001B03000101B489860624700093459875FFFFFFFFFFFF{vin}FFFFFFFFFFFFFFFF"
# 计算CRC-16校验和
data1 = bytes.fromhex(data0 + data)
crc_result = crc16(data1)
login_data = data + crc_result



# 心跳数据
now = datetime.now()
time0 = decimal_to_hex([now.year % 100, now.month, now.day, now.hour, now.minute, now.second])
SOH = formatx(98)
SOC = formatx(15)
TotalMileage = format6(-19)
batterySN = "400411099999".encode('ASCII').hex()  # 12位电池序列号400411000110  0PFPBECLG079
# batterySN="FFFFFFFFFFFFFFFFFFFFFFFF"
# 组合数据
data3 = f"D2CF008604{TBOXCode}8F18{time0}{SOH}FFFFFFFFFF0102FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00{TotalMileage}011019CB470D{SOC}FFFF00000006F74A30022E0534FFFF02FFFFFF00FFFFFF00FFFFFFFFFFFFFFFFFFFFFFFF014BFFFFFFFF0CFFFFFF040000FFFFFFFF000C4A0002C6000C2C00000000001E6007{batterySN}"

datacrc = bytes.fromhex(data0 + data3)
crc_result1 = crc16(datacrc)
heartbeat_data = data3 + crc_result1

# 电池详细参数(0x2d)
maxtemp = formatx(55)  # 电芯温度最大值
mintemp = formatx(55)  # 电芯温度最小值
avgtemp = formatx(55)  # 电芯温度平均值
maxcsc = formatx(55)  # 电芯温度最大值所在CSC编号
maxcscno = formatx(55)  # 电芯温度最大值所在CSC编号内温度探针编号
mincsc = formatx(55)  # 电芯温度最小值所在CSC编号
mincscno = formatx(54)  # 电芯温度最小值所在 CSC内温度探针编号
maxvcsc = formatx(55)  # 电芯电压最大值所在CSC编号
maxvcscno = formatx(54)  # 电芯电压最大值所在CSC内单体编号
minvcsc = formatx(55)  # 电芯电压最小值所在CSC编号
minvcscno = formatx(55)  # 电芯电压最小值所在CSC内单体编号
# 组合数据
data4 = f"D2CF004A04{TBOXCode}762D{time0}{maxtemp}{mintemp}{avgtemp}{maxcsc}{maxcscno}{mincsc}{mincscno}{maxvcsc}{maxvcscno}{minvcsc}{minvcscno}FF4E203C9C183818320DA60C9E0C9802040101020080FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
datacrc2 = bytes.fromhex(data0 + data4)
crc_result2 = crc16(datacrc2)
# 换电站数据组合
battery_data = data4 + crc_result2

# 换电站协议数据(0x26)
time2 = decimal_to_hex([25, 2, 10, 8, 45, 22])
temper1 = formatx(11)
temper2 = formatx(11)
temper3 = formatx(11)
temper4 = formatx(11)
temper5 = formatx(11)
temper6 = formatx(11)
temper7 = formatx(11)
temper8 = formatx(11)

data5 = f"D2CF005D04{TBOXCode}5626{time0}0131323334353637383930313233340001000000010100{temper1}{temper2}{temper3}{temper4}{temper5}{temper6}{temper7}{temper8}0000000000000000000000000000000000000000000000000000000000000000000000000000000000E20101080000"
datacrc3 = bytes.fromhex(data0 + data5)
crc_result3 = crc16(datacrc3)
# 换电站协议数据组合
station_data = data5 + crc_result3

ip = "101.132.254.135"      #FAT服务器IP地址
# ip = "47.100.187.205"  # UAT服务器IP地址
port = 8089


# login_data    battery_data   heartbeat_data    station_data
login_messages = [login_data]
hex_messages2 = [heartbeat_data, battery_data, station_data]  # 可以发送多个数据包

if __name__ == "__main__":
    sock = create_tcp_connection(ip, port)
    for i in range(1):
        print("第" + str(i) + "次")
        time.sleep(1)
        send_messages(sock, login_messages)
        send_messages(sock, hex_messages2)
    close_tcp_connection(sock)
